﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpDX.Toolkit.Graphics;
using SharpDX.Direct3D11;
using SharpDX;
using Texture2D = SharpDX.Toolkit.Graphics.Texture2D;


namespace Ignitron.EEngine.Adapters.DX.Graphics
{
    /// <summary>
    /// SharpDX rendering texture
    /// </summary>
    internal class SharpDXRenderTexture: SharpDXTexture
    {
        /// <summary>
        /// DX11 Wrapper class
        /// </summary>
        private DX11 mDX11;

        /// <summary>
        /// Rendering for 2D graphics
        /// </summary>
        private SpriteBatch mBatch;

        /// <summary>
        /// Rendering texture target
        /// </summary>
        private SharpRenderTarget mTarget;

        /// <summary>
        /// Graphics device
        /// </summary>
        private GraphicsDevice mGraphicsDevice;


        /// <summary>
        /// Constructor
        /// </summary>
        public SharpDXRenderTexture(DX11 dx11, int width, int height) :
            base(dx11.Device)
        {
            mTarget = new SharpRenderTarget(mDevice, width, height, SharpDX.DXGI.Format.B8G8R8A8_UNorm);
            mGraphicsDevice = GraphicsDevice.New(mDevice);
            mBatch = new SpriteBatch(mGraphicsDevice);
            mDX11 = dx11;
        }

        /// <summary>
        ///  Frees the resources
        /// </summary>
        public override void Shutdown()
        {
            if (mTarget != null)
            {
                mTarget.Dispose();
                mTarget = null;
            }
            if (mBatch != null)
            {
                mBatch.Dispose();
                mBatch = null;
            }
            if (mGraphicsDevice != null)
            {
                mGraphicsDevice.Dispose();
                mGraphicsDevice = null;
            }

            base.Shutdown();
        }

        /// <summary>
        /// Binds the rendering target
        /// </summary>
        public void BindTarget()
        {
            mTarget.Apply();
            mTarget.Clear(SharpDX.Color.Black);
        }

        /// <summary>
        /// Restores previous viewport
        /// </summary>
        public void UnbindTarget(int width, int height)
        {
            mDX11.SetDefaultTargets(width, height);            
        }

        /// <summary>
        /// Renders a filled rect
        /// </summary>
        internal void DrawRect(int x, int y, int width, int height, Vector4 color)
        {
            Texture2D txt = Texture2D.New(mGraphicsDevice, 1, 1, MipMapCount.Auto, PixelFormat.R8G8B8A8.UNorm, null);
            txt.SetData<Color>(new Color[] { new Color(color)});
            mBatch.Begin();
            mBatch.Draw(txt, new RectangleF((float)x, (float)y, (float)width, (float)height), Color.White);
            mBatch.End();
        }

        /// <summary>
        /// Renders a texture
        /// </summary>
        internal void DrawTexture(int x, int y, int width, int height, SharpDXTexture texture)
        {
            mBatch.Begin();
            mBatch.Draw(texture.GetResource(), new RectangleF((float)x, (float)y, (float)width, (float)height), Color.White);
            mBatch.End();
        }

        /// <summary>
        /// Returns the specific resource
        /// </summary>
        /// <returns></returns>
        internal override ShaderResourceView GetResource()
        {
            return mTarget.Resource;
        }
    }
}
